﻿using Common.Framework.Core.Extension;
using Microsoft.AspNetCore.Http;
using Serilog;
using Snowflake.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common.Framework.Core.SqlSugar;
using System.Configuration;
using Serilog.Events;

namespace Common.Framework.Core.Serilog
{
    public static class LoggerHelper
    {
        private static IdWorker idWorker = new IdWorker(1, Convert.ToInt32(ConfigurationExtension.Configuration["ServerNodeNo"]));

        /// <summary>
        /// 记录业务日志-新增
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="logObjType">业务对象类型(比如Oder/User等)</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationInsert(string message, string logObjType, string operatorId = "", HttpRequest request = null)
        {
            Log.ForContext("ObjType", logObjType).ForContext("OperationType", Convert.ToInt32(LogOperationType.Insert)).ForContext("OperatorUid", operatorId).ForContext("Ip", GetClientIp(request)).Information(message);
        }

        /// <summary>
        /// 记录业务日志-新增
        /// </summary>
        /// <typeparam name="TEntity">业务对象类型(比如Oder/User等)</typeparam>
        /// <param name="message">需要记录的信息</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request"></param>
        public static void InformationInsert<TEntity>(string message, string operatorId = "", HttpRequest request = null)
        {
            InformationInsert(message, typeof(TEntity).Name, operatorId, request);
        }

        /// <summary>
        /// 记录业务日志-删除
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="logObjType">业务对象类型(比如Oder/User等);请重写LogObjType类</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationDelete(string message, string logObjType, string operatorId = "", HttpRequest request = null)
        {
            Log.ForContext("ObjType", logObjType).ForContext("OperationType", Convert.ToInt32(LogOperationType.Delete)).ForContext("OperatorUid", operatorId).ForContext("Ip", GetClientIp(request)).Information(message);
        }

        /// <summary>
        /// 记录业务日志-删除
        /// </summary>
        /// <typeparam name="TEntity">业务对象类型(比如Oder/User等)</typeparam>
        /// <param name="message">需要记录的信息</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationDelete<TEntity>(string message, string operatorId = "", HttpRequest request = null)
        {
            InformationDelete(message, typeof(TEntity).Name, operatorId, request);
        }

        /// <summary>
        /// 记录业务日志-更新
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="logObjType">业务对象类型(比如Oder/User等);请重写LogObjType类</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationUpdate(string message, string logObjType, string operatorId = "", HttpRequest request = null)
        {
            Log.ForContext("ObjType", logObjType).ForContext("OperationType", Convert.ToInt32(LogOperationType.Update)).ForContext("OperatorUid", operatorId).ForContext("Ip", GetClientIp(request)).Information(message);
        }

        /// <summary>
        /// 记录业务日志-更新
        /// </summary>
        /// <typeparam name="TEntity">业务对象类型(比如Oder/User等)</typeparam>
        /// <param name="message">需要记录的信息</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationUpdate<TEntity>(string message, string operatorId = "", HttpRequest request = null)
        {
            InformationUpdate(message, typeof(TEntity).Name, operatorId, request);
        }
        /// <summary>
        /// 记录业务日志-查询
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="logObjType">业务对象类型(比如Oder/User等);请重写LogObjType类</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationQuery(string message, string logObjType, string operatorId = "", HttpRequest request = null)
        {
            Log.ForContext("ObjType", logObjType).ForContext("OperationType", Convert.ToInt32(LogOperationType.Query)).ForContext("OperatorUid", operatorId).ForContext("Ip", GetClientIp(request)).Information(message);
        }

        /// <summary>
        /// 记录业务日志-查询
        /// </summary>
        /// <typeparam name="TEntity">业务对象类型(比如Oder/User等)</typeparam>
        /// <param name="message">需要记录的信息</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationQuery<TEntity>(string message, string operatorId = "", HttpRequest request = null)
        {
            InformationQuery(message, typeof(TEntity).Name, operatorId, request);
        }

        /// <summary>
        /// 记录业务日志-其它
        /// </summary>
        /// <param name="message">需要记录的信息</param>
        /// <param name="logObjType">业务对象类型(比如Oder/User等);请重写LogObjType类</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationOther(string message, string logObjType, string operatorId = "", HttpRequest request = null)
        {
            Log.ForContext("ObjType", logObjType).ForContext("OperationType", Convert.ToInt32(LogOperationType.Other)).ForContext("OperatorUid", operatorId).ForContext("Ip", GetClientIp(request)).Information(message);
        }

        /// <summary>
        /// 记录业务日志-其它
        /// </summary>
        /// <typeparam name="TEntity">业务对象类型(比如Oder/User等)</typeparam>
        /// <param name="message">需要记录的信息</param>
        /// <param name="operatorId">操作人id</param>
        /// <param name="request">客户端Ip</param>
        public static void InformationOther<TEntity>(string message, string operatorId = "", HttpRequest request = null)
        {
            InformationOther(message, typeof(TEntity).Name, operatorId, request);
        }

        /// <summary>
        /// 记录sql语句
        /// </summary>
        /// <param name="message">sql语句</param>
        /// <param name="tmpParams">参数</param>
        public static void InformationSql(string message, string tmpParams)
        {
            Log.ForContext("ObjType", "Sql").ForContext("OperationType", Convert.ToInt32(LogOperationType.Query)).Information(message);
        }

        /// <summary>
        /// 记录业务日志
        /// </summary>
        /// <param name="entity"></param>
        public static void Information(LogEntityRequest entity)
        {
            int OperationType = GetOperationType(entity.OperationType);
            long Operatorid = CurrentUserId(entity.Request);
            Log.ForContext("Id", GenerateId())
               .ForContext("ObjType", entity.LogObjType)
               .ForContext("LogObjTypeAlias", entity.LogObjTypeAlias)
               .ForContext("OperationName", entity.OperationName)
               .ForContext("OperationType", OperationType)
               .ForContext("Level", entity.Level)
               .ForContext("OperatorId", Operatorid)
               .ForContext("OperateIp", GetClientIp(entity.Request))
               .ForContext("ServerMark", entity.ServerMark)
               .ForContext("DeleteFlag", 0)
               .ForContext("CreateTime", DateTime.Now)
               .Information(entity.Message);
        }

        public static void Error(LogEntityRequest entity)
        {
            int OperationType = GetOperationType(entity.OperationType);

            long Operatorid = 0;
            if (!entity.OperationType.ToLower().Contains("login"))
            {
                Operatorid = CurrentUserId(entity.Request);
            }
            Log.ForContext("Id", GenerateId())
               .ForContext("ObjType", entity.LogObjType)
               .ForContext("LogObjTypeAlias", entity.LogObjTypeAlias)
               .ForContext("OperationName", entity.OperationName)
               .ForContext("OperationType", OperationType)
               .ForContext("Level", entity.Level)
               .ForContext("OperatorId", Operatorid)
               .ForContext("OperateIp", GetClientIp(entity.Request))
               .ForContext("ServerMark", entity.ServerMark)
               .ForContext("DeleteFlag", 0)
               .ForContext("CreateTime", DateTime.Now)
               .Error(entity.Message);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Name"></param>
        /// <returns></returns>
        private static int GetOperationType(string Name)
        {
            Name = Name.ToLower();
            int OperationType = Convert.ToInt32(LogOperationType.Other);
            if (Name.Contains("create"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Insert);
            }
            else if (Name.Contains("update"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Update);
            }
            else if (Name.Contains("delete"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Delete);
            }
            else if (Name.Contains("export"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Export);
            }
            else if (Name.Contains("import"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Import);
            }
            else if (Name.Contains("login"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Login);
            }
            else if (Name.Contains("query") || Name.Contains("get"))
            {
                OperationType = Convert.ToInt32(LogOperationType.Query);
            }
            return OperationType;
        }
        private static string GetClientIp(HttpRequest request)
        {
            string clientIp = "";
            if (request != null)
            {
                clientIp = request.GetRemoteIpAddress();
                if (clientIp.Length >= 50)
                {
                    clientIp = clientIp.Substring(0, 49);
                }
            }
            return clientIp;
        }
        /// <summary>
        /// 当前用户名
        /// </summary>
        private static long CurrentUserId(HttpRequest request)
        {
            var userClaim = request.HttpContext.User.Claims.FirstOrDefault(s => s.Type == "id");
            if (userClaim != null)
            {
                return Convert.ToInt64(userClaim.Value);
            }
            return 0;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static long GenerateId()
        {
            return idWorker.NextId();
        }
    }
}
